"""
Draw the result of the parsing in the appropiate PNG file
"""

from xml.dom import minidom
from xml import dom
import tree

__all__ = [ 'Drawer' ]

BASIC_SVG = """\
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="%spx" height="%spx" version="1.0" xmlns="http://www.w3.org/2000/svg">
</svg>
"""

class Drawer():
    """
    Takes the n-ary tree built from Parsers and draws an SVG file
    """

    def __init__(self, tree, options):
        """
        Initialize the class
        """
        self.options = options
        self.parseTree = tree
        self.output_filename = options['output']
        self.width = options['width']
        self.height = options['height']
        self.title = "Pytagram generated file"
        self.svgId = 1000
        self.levelx = 10
        self.levely = 10
        self.step = options['step']

        self.dom = minidom.parseString(BASIC_SVG % (self.width, self.height))
        cmt = self.dom.createComment('Generated with Pytagram')
        self.dom.documentElement.appendChild(cmt)

    def draw(self):
        """
        Begins the tree generation, setting up root nodes and other needed
        stuff
        """
        domRoot = self.dom.documentElement
        parseRoot = self.parseTree

        self.dom.documentElement.appendChild(self._draw(parseRoot, domRoot))

        f = open(self.output_filename, 'w')
        f.write(self.dom.toprettyxml())
        f.close()

        return True


    def _draw(self, parseTreeNode, domNode):
        """
        Given the node tree, updates the DOM starting from that node
        """
        nn = parseTreeNode.parentTree

        if parseTreeNode.type == tree.TYPE_NAMESPACE:
            item = self.typeNamespace(nn, self.levelx, self.levely)
        elif parseTreeNode.type == tree.TYPE_CLASS:
            item = self.typeClass(nn, self.levelx, self.levely)
        elif parseTreeNode.type == tree.TYPE_FUNC:
            item = self.typeFunc(nn, self.levelx, self.levely)

        newNode = domNode.appendChild(item)

        for parseSon in parseTreeNode.nextSon():
            self.levely = self.levely + self.step
            self.levelx = self.levelx + self.step
            newNode.appendChild(self._draw(parseSon, newNode))
        self.levelx = self.levelx - self.step

        return newNode


    def svgRect(self):
        """
        Create a SVG ``rect`` element
        """
        return self.dom.createElement('rect')

    def svgText(self, text):
        """
        Create a SVG ``text`` element
        """
        txt = self.dom.createTextNode(text)
        node = self.dom.createElement('text')

        node.appendChild(txt)
        node.setAttribute('id', 'item' + self.genSvgId())
        node.setAttribute('font-size', '12px')
        node.setAttribute('font-family', 'Monospace')

        return node

    def svgBox(self, textValue, bg="#000000", fg="#FFFFFF", x=None, y=None):
        """
        Create a rectangle with the specified text within. The rect width
        is adjusted according to the text's length.
        """

        # TODO: rect width should be better adjusted, as we would like to
        # be able to change the font to some other typeface than Monospace

        if not x:
            x = 0
        if not y:
            y = 0

        group = self.dom.createElement('g')

        rect = self.svgRect()
        text = self.svgText(textValue)

        group.appendChild(rect)
        group.appendChild(text)
        group.setAttribute('id', 'item' + self.genSvgId())

        rect.setAttribute('height', '25px')
        width = int((len(textValue) * 12)/1.5)
        rect.setAttribute('width', str(width) + "px")
        rect.setAttribute('fill', bg)
        text.setAttribute('fill', fg)

        rect.setAttribute('x', str(x))
        rect.setAttribute('y', str(y))
        text.setAttribute('x', str(x + 5))
        text.setAttribute('y', str(y + 15))

        return group

    def genSvgId(self):
        """
        Returns an incremental id for universally identifying elements within
        the resulting SVG file.
        The 'id' stuff is not really required, but could be useful for eventual
        animation stuff (think at javascript)
        """
        self.svgId = self.svgId + 1
        return str(self.svgId)

    def typeNamespace(self, value, x, y):
        """
        Build a composite SVG element for representing a namespace
        """
        return self.svgBox(value, self.options['bg_namespace'], self.options['fg_namespace'], x=x, y=y)

    def typeClass(self, value, x, y):
        """
        Build a composite SVG element for representing a class
        """
        return self.svgBox(value, self.options['bg_class'], self.options['fg_class'], x=x, y=y)

    def typeFunc(self, value, x, y):
        """
        Build a composite SVG element for representing a method or function
        """
        return self.svgBox(value, self.options['bg_func'], self.options['fg_func'], x=x, y=y)
